package com.thyrsus.project.dao.user;

import java.util.ArrayList;
import java.util.List;

import javax.persistence.EntityManager;
import javax.persistence.Query;

import org.apache.log4j.Logger;
import org.springframework.stereotype.Repository;

import com.google.appengine.api.datastore.Key;
import com.thyrsus.project.dao.EMFService;
import com.thyrsus.project.dao.IDao;
import com.thyrsus.project.dao.event.entity.Event;
import com.thyrsus.project.dao.user.entity.User;
import com.thyrsus.project.object.UserContext;


@Repository
public class UserDAO extends IDao<User>{

	private String[] searchElements = {"firstName","lastName"};
	
	static Logger LOGGER = Logger.getLogger(UserDAO.class);
	
	@SuppressWarnings("unchecked")
	public List<User> listUsers() {
		EntityManager em = EMFService.get().createEntityManager();
		// Read the existing entries
		Query q = em.createQuery("select m from User m");
		List<User> users = q.getResultList();
		return users;
	}

	@SuppressWarnings("unchecked")
	public List<User> getUsers(String mail) {
		EntityManager em = EMFService.get().createEntityManager();
		Query q = em
				.createQuery("select t from User t where t.mail = :userMail");
		q.setParameter("userMail", mail);
		List<User> users = q.getResultList();
		return users;
	}
	
	@SuppressWarnings("unchecked")
	public boolean hasAdmin() {
		EntityManager em = EMFService.get().createEntityManager();
		Query q = em
				.createQuery("select t from User t where t.isAdmin = true");
		List<User> users = q.getResultList();
		return users!=null && users.size()>0;
	}

	public void remove(long id) {
		EntityManager em = EMFService.get().createEntityManager();
		try {
			User user = em.find(User.class, id);
			em.remove(user);
		} finally {
			em.close();
		}
	}
	
	public void removeAll() {
		EntityManager em = EMFService.get().createEntityManager();
		Query q = em.createQuery("delete from User");
		q.executeUpdate();
	}
	
	public void addCreatedEvent(Event event,UserContext user) {
		EntityManager em = EMFService.get().createEntityManager();
		try {
			em.getTransaction().begin();
			User userx = em.find(User.class, user.getId());
			
			userx.addCreatedEvent(event);
			
			em.persist(userx);
			
			em.getTransaction().commit();
		} catch(Exception e) {
			e.printStackTrace();
		} finally {
			if (em.getTransaction().isActive()) {
				em.getTransaction().rollback();
			}
			em.close();
		}
	}
	
	public List<Key> getCreatedEvent(UserContext user) {
		EntityManager em = EMFService.get().createEntityManager();
		List<Key> list = new ArrayList<Key>();
		User userx = null;
		try {
			userx = em.find(User.class, user.getId());
			list = userx.getCreatedEvents();
		} catch(Exception e) {
			e.printStackTrace();
		} finally {
			em.close();
		}
		
		
		return list;
	}
	
	public User getUser(UserContext user) {
		EntityManager em = EMFService.get().createEntityManager();
		User userx = null;
		try {
			userx = em.find(User.class, user.getId());
		} catch(Exception e) {
			e.printStackTrace();
		} finally {
			em.close();
		}
		
		
		return userx;
	}
	
	public User getUser(Long userId) {
		EntityManager em = EMFService.get().createEntityManager();
		User userx = null;
		try {
			userx = em.find(User.class, userId);
		} catch(Exception e) {
			e.printStackTrace();
		} finally {
			em.close();
		}
		
		
		return userx;
	}
	
	public void update(UserContext user) {
		EntityManager em = EMFService.get().createEntityManager();
		try {
			em.getTransaction().begin();
			//User userx = em.find(User.class, user.getId());
			/**Should add a specific method for list elements....**/
			//userx.addEvent("default", new Event());
			
			em.getTransaction().commit();
		} catch(Exception e) {
			e.printStackTrace();
		} finally {
			if (em.getTransaction().isActive()) {
				em.getTransaction().rollback();
			}
			em.close();
		}
	}
	
	public boolean removeCreatedEvent(UserContext user,Event event) {
		EntityManager em = EMFService.get().createEntityManager();
		boolean result =  false;
		try {
			em.getTransaction().begin();
			User userx = em.find(User.class, user.getId());
			
			result = userx.removeCreatedEvent(event);
			
			em.persist(userx);
			
			em.getTransaction().commit();
		} catch(Exception e) {
			e.printStackTrace();
		} finally {
			if (em.getTransaction().isActive()) {
				em.getTransaction().rollback();
			}
			em.close();
		}
		return result;
	}
	
	@SuppressWarnings("unchecked")
	public List<User> searchUsers(String searchString) {

		List<User> users = new ArrayList<User>();
		EntityManager em = EMFService.get().createEntityManager();
		
		Query q = null;
		List<String>queries = buildSearchQuery(searchString);
		for (String query : queries) {
			LOGGER.debug(query);
			q = em.createQuery(query);
			
			users.addAll(q.getResultList());
		}
		return users;
	}

	private List<String> buildSearchQuery(String searchString) {
		List<String>queries = new ArrayList<String>();
		String searchStringSplitted[] = searchString.split(" ");
		String requestFirst = "";
		String requestLast = "";
		String query = null;
		if (!("".equals(searchString) || searchString.matches(" "))) {
			query="SELECT u FROM User u WHERE ";
			String queryWhere = "(UPPER(u."+searchElements[0]+") LIKE '"+searchString.toUpperCase()+"%')";
			queries.add(query+queryWhere);
			queryWhere = "(UPPER(u."+searchElements[1]+") LIKE '"+searchString.toUpperCase()+"%')";
			queries.add(query+queryWhere);
			for (int i = 0 ; i < searchStringSplitted.length ; i++) {
				requestFirst = "";
				requestLast = "";
				for (int j = 0; j < i ; j ++) {
					requestFirst+=searchStringSplitted[j];
				}
				for (int j = i; j < searchStringSplitted.length ; j ++) {
					requestLast+=searchStringSplitted[j];
				}
				queryWhere="(UPPER(u."+searchElements[0]+")="+getEqualElement(requestFirst)+" AND UPPER(u."+searchElements[1]+")="+getEqualElement(requestLast)+")";
				queries.add(query+queryWhere);
				queryWhere="(UPPER(u."+searchElements[1]+")="+getEqualElement(requestFirst)+" AND UPPER(u."+searchElements[0]+")="+getEqualElement(requestLast)+")";
				queries.add(query+queryWhere);
				
			}
			query+=queryWhere;
			
			
		}
		return queries;
	}
	
	private String getEqualElement(String element) {
		if ("".equals(element)) {
			return "''";
		} else {
			return "'"+element.toUpperCase()+"'";
		}
	}
}